/*

 switchsound.c - a FreeBSD utility to toggle between speakers and 
 headphone jack sound output. Requires the built-in mixer(8) utility.

 This program is Free Software released under the terms and conditions of
 the GNU GPL v3. See https://www.gnu.org/licenses for more information.

 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Some hardcoded constants:
#define TUNABLE "sysctl hw.snd.default_unit"

// The maximum output of this command is about 27char, so have a buffer:
#define CMD_OUTPUT_MAX 32

int
get_default_unit()
{
    int status = 0;

    FILE* p = popen(TUNABLE, "r");

    if (!p) {
        printf("Error: failed to query sound status!\n");
        return -1;
    }

    // buffer to read output from command.
    char output[CMD_OUTPUT_MAX];

    fgets(output, CMD_OUTPUT_MAX, p);

    for (int i = 0; i < CMD_OUTPUT_MAX; i++) {
        if (output[i] == '\n') {
            output[i] = '\0';
        }
    }

    // can "cheat" here because the length is always the same:
    status = atoi(&output[21]);

    //printf("The command seems to return sound device %d\n", status);

    pclose(p);

    return status;
}

int
set_default_unit()
{
    FILE* proc;
    char* command;
    char buffer[CMD_OUTPUT_MAX];

    int unit = get_default_unit();

    if (unit == 0) {
        unit = 1;
        asprintf(&command, "%s=1", TUNABLE);
    }
    else {
        unit = 0;
        asprintf(&command, "%s=0", TUNABLE);
    }

    printf("Toggling to sound unit %d\n", unit);

    proc = popen(command, "r");
    if (proc == NULL) {
        printf("Command failed.\n");
        return -1;
    }

    // do "something" so the command gets executed.
    fgets(buffer, CMD_OUTPUT_MAX, proc);

    pclose(proc);
    free(command);

    return get_default_unit();
}

int
main(int argc, char* argv[]) 
{
    int unit = get_default_unit();   

    unit = set_default_unit();

    printf("The default unit is now: %d\n", unit);

    return 0;
}
